



import bpy
import bmesh
import math
import mathutils


import engine.initLIB.load_dll as engineLib
import ctypes


def f_右手坐标系转左手坐标系(me):
	bm = bmesh.new()
	bm.from_mesh(me)
	bmesh.ops.rotate(bm, verts=bm.verts[:], cent=(1.0, 0.0, 0.0), matrix=mathutils.Matrix.Rotation(math.radians(-90.0), 3, 'X'))
	bmesh.ops.scale(bm, vec=mathutils.Vector((1.0, 1.0, -1.0)), space=mathutils.Matrix.Scale(1, 4, (1.0, 1.0, 1.0)), verts=bm.verts[:])
	bm.to_mesh(me)
	bm.free()

def f_坐标系_PX_upY_backwardZ(me):
	bm = bmesh.new()
	bm.from_mesh(me)
	bmesh.ops.rotate(bm, verts=bm.verts[:], cent=(1.0, 0.0, 0.0), matrix=mathutils.Matrix.Rotation(math.radians(-90.0), 3, 'X'))
	#bmesh.ops.scale(bm, vec=mathutils.Vector((1.0, 1.0, -1.0)), space=mathutils.Matrix.Scale(1, 4, (1.0, 1.0, 1.0)), verts=bm.verts[:])
	bm.to_mesh(me)
	bm.free()


def f_左手坐标系转右手坐标系(me):
	bm = bmesh.new()
	bm.from_mesh(me)
	bmesh.ops.scale(bm, vec=mathutils.Vector((1.0, 1.0, -1.0)), space=mathutils.Matrix.Scale(1, 4, (1.0, 1.0, 1.0)), verts=bm.verts[:])
	bmesh.ops.rotate(bm, verts=bm.verts[:], cent=(1.0, 0.0, 0.0), matrix=mathutils.Matrix.Rotation(math.radians(90.0), 3, 'X'))
	bm.to_mesh(me)
	bm.free()



def f_变换矩阵_右手坐标系转左手坐标系(obj):
	物体矩阵 = mathutils.Matrix()
	
	物体矩阵 = 物体矩阵.Rotation(math.radians(-90.0), 4, 'X')
	物体矩阵 = 物体矩阵.Scale(-1.0, 4, (0.0, 0.0, 1.0))
	
	#loc, rot, sca = 物体矩阵.decompose()
	rot = 物体矩阵 @ mathutils.Vector(obj.rotation_euler)
	rot[0] = math.degrees(rot[0])
	rot[1] = -math.degrees(rot[1])
	rot[2] = math.degrees(rot[2])
	return [tuple(物体矩阵 @ obj.location), tuple(rot), tuple(物体矩阵 @ obj.scale)]
	




def f_mesh_triangulate(me):
	bm = bmesh.new()
	bm.from_mesh(me)
	bmesh.ops.triangulate(bm, faces=bm.faces)
	bm.to_mesh(me)
	bm.free()





def f_get物体网格数据(obj, context, 引用修改器=True, 导出三角面=True, 转换坐标系=True, 应用矩阵=False, 封包=True):
	#depsgraph = bpy.context.evaluated_depsgraph_get()
	depsgraph = context.evaluated_depsgraph_get()
	
	顶点 = []
	法线 = []
	索引 = []
	面法线 = []
	面中心 = []
	面材质ID = []
	材质槽 = []

	try:
		#for dup in depsgraph.object_instances
		#	if dup.parent and dup.parent.original == ob_main]
		ob_for_convert = obj.evaluated_get(depsgraph)
		me = ob_for_convert.to_mesh()
		#me = obj.to_mesh(preserve_all_data_layers=引用修改器, depsgraph=depsgraph) #
		#me = ob_for_convert.to_mesh() #, depsgraph=depsgraph
	except RuntimeError:
		me = None

	if 应用矩阵 :
		me.transform(obj.matrix_basis)
	

	#if 转换坐标系 :
	#	f_坐标系_PX_upY_backwardZ(me)
	if 导出三角面 :
		f_mesh_triangulate(me)
		
		
	#材质槽 = list(obj.data.materials)
	for mat in me.materials:
		材质槽.append((bpy.data.materials[mat.name], mat.as_pointer()))


	me_verts = me.vertices[:]
	for v in me_verts:
		顶点.append(tuple(v.co))
		法线.append(tuple(v.normal))
		
	if 封包 :
		UV = [(0.0,0.0)] * len(顶点)

		loops = me.loops
		UV层 = me.uv_layers.active
		for polygon in me.polygons:
			_index = []
			for i in range(polygon.loop_total):
				顶点索引 = polygon.loop_start + i
				vertex_index = loops[顶点索引].vertex_index
				_index.append( int(vertex_index) )
				
				if UV层 != None :
					UV[vertex_index] = tuple(UV层.data[顶点索引].uv)
			索引.append(_index[::-1])

			面法线.append(tuple(polygon.normal))
			面中心.append(tuple(polygon.center))
			面材质ID.append(polygon.material_index)

		纹理坐标 = []
		for layer in me.uv_layers:
			坐标 = []
			for coord in layer.data:
				坐标.append(tuple(coord.uv))
			纹理坐标.append(坐标)
			
		return [list(''), 顶点, 法线, UV, 纹理坐标, 索引, 面法线, 面中心, [], [], [], 面材质ID, 材质槽]

	else:
		环 = []
		for loops in me.loops:
			环.append((loops.vertex_index, loops.edge_index))
			
		边 = []
		for edge in me.edges:
			边.append(edge.key)
			
		顶点索引 = []
		多边形 = []
		for polygon in me.polygons:
			p = (	polygon.loop_total, 
					polygon.loop_start, 
					polygon.area, 
					polygon.material_index
				)
			多边形.append(p)
			顶点索引.append(list(polygon.vertices))
			面法线.append(tuple(polygon.normal))
			面中心.append(tuple(polygon.center))

		纹理坐标 = []
		for layer in me.uv_layers:
			坐标 = []
			for coord in layer.data:
				坐标.append(tuple(coord.uv))
			纹理坐标.append(坐标)

		return [顶点, 法线, 纹理坐标, 顶点索引, 面法线, 面中心, 边, 环, 多边形, 材质ID, 材质槽]














def f_get物体体素(objs, context, 包围盒=(), 间距=(), 引用修改器=True, 导出三角面=True):
	depsgraph = context.depsgraph
	#mainBm = bmesh.new()
	#f_右手坐标系转左手坐标系()
	#包围盒 = tuple(Lower+Upper)
	顶点 = []
	索引 = []
	UV = []

	测试索引 = []
	索引偏移 = 0
	for obj in objs:
		try:
			me = obj.to_mesh(depsgraph, 引用修改器)
		except RuntimeError:
			me = None
		me.transform(obj.matrix_basis)
		
		f_右手坐标系转左手坐标系(me)
		if 导出三角面 :
			f_mesh_triangulate(me)
		
		#mesh.vertices.foreach_get("co", np.reshape(vertices, len(mesh.vertices) * 3))
		me_verts = me.vertices[:]
		for v in me_verts:
			顶点.append(tuple(v.co))
		#print('顶点 = ', type(顶点), 顶点)
		loops = me.loops

		uv_face_mapping = [None] * len(me.polygons)
		for polygon in me.polygons:
			_index = []
			for i in range(polygon.loop_total):
				顶点索引 = polygon.loop_start + i
				vertex_index = loops[顶点索引].vertex_index
				_index.append( int(vertex_index + 索引偏移) )
				#索引.append( int(vertex_index + 索引偏移) )
			索引.extend(_index[::-1])
				##_index.append( int(vertex_index + 索引偏移) )
			#测试索引.append(tuple(_index))
		'''face_index_pairs = [(face, index) for index, face in enumerate(me.polygons)]
		for f, f_index in face_index_pairs:
			for uv_index, l_index in enumerate(f.loop_indices):
				#print('uv_index = ', loops[l_index].vertex_index)
				索引.append( int(loops[l_index].vertex_index + 索引偏移) )'''
				
		索引偏移 += len(me_verts)
		
		

	体素 = []
	engineLib.flexCAPI.f_get模型体素.restype = ctypes.py_object #ctypes.py_object(体素), 
	体素 = engineLib.flexCAPI.f_get模型体素(ctypes.py_object(顶点), ctypes.py_object(索引), ctypes.py_object(包围盒), ctypes.py_object(间距))
	
	
	
	
	return 体素



